﻿namespace Beetle.Clients
{
    using Beetle;
    using Smark.Core;
    using System;
    using System.Collections.Generic;
    using System.Runtime.CompilerServices;
    using System.Threading;

    public class TcpSyncNode : IDisposable
    {
        private int _field_a;
        private Exception _field_b;
        private Queue<TcpSyncNode_a> _field_c = new Queue<TcpSyncNode_a>();
        private Type _field_d;
        private bool _field_e;
        [CompilerGenerated]
        private string _field_f;
        [CompilerGenerated]
        private int _field_g;
        [CompilerGenerated]
        private int _field_h;
        [CompilerGenerated]
        private string _field_i;
        [CompilerGenerated]
        private int _field_j;
        [CompilerGenerated]
        private NodeStatus _field_k;

        public TcpSyncNode(string host, int port, int maxconnections)
        {
            this.Host = host;
            this.Port = port;
            this.Status = NodeStatus.Error;
            this.DetectTime = 30;
            this.MaxConnections = maxconnections;
        }

        private void a()
        {
            try
            {
                TcpSyncNode_a _a = this.b();
                this.a(_a);
                if ((this.Status == NodeStatus.None) && (this._field_c.Count < this.MaxConnections))
                {
                    this.AsynCreateChannel();
                }
            }
            catch (Exception exception)
            {
                this._field_b = exception;
            }
        }

        internal void a(TcpSyncNode_a A_0)
        {
            lock (this)
            {
                if (A_0 != null)
                {
                    this._field_c.Enqueue(A_0);
                }
            }
        }

        internal void a(Exception A_0)
        {
            this.Status = NodeStatus.Error;
            this._field_b = A_0;
            this._field_a = Environment.TickCount;
        }

        public void AsynCreateChannel()
        {
            lock (this)
            {
                if (this._field_c.Count < this.MaxConnections)
                {
                    Functions.Action(new AsyncDelegate(this.a));
                }
            }
        }

        private TcpSyncNode_a b()
        {
            try
            {
                TcpSyncNode_a _a = new TcpSyncNode_a();
                ITcpSyncChannel channel = (ITcpSyncChannel) Activator.CreateInstance(this._field_d);
                channel.Connect(this.Host, this.Port);
                _a.a(channel);
                this.Status = NodeStatus.None;
                return _a;
            }
            catch (Exception exception)
            {
                this._field_a = Environment.TickCount;
                this.Status = NodeStatus.Error;
                this._field_b = exception;
            }
            return null;
        }

        internal TcpSyncNode_a c()
        {
            TcpSyncNode_a _a = null;
            if (this.Status != NodeStatus.Error)
            {
                int num = 1;
                while (num < 20)
                {
                    lock (this)
                    {
                        if (this._field_c.Count > 0)
                        {
                            _a = this._field_c.Dequeue();
                            _a.a(this);
                            return _a;
                        }
                        Thread.Sleep(10);
                        num++;
                        continue;
                    }
                }
            }
            return _a;
        }

        public void CheckState()
        {
            lock (this)
            {
                if ((Environment.TickCount - this._field_a) > (this.DetectTime * 0x3e8))
                {
                    this._field_a = Environment.TickCount;
                    if (this.Status == NodeStatus.Error)
                    {
                        this.AsynCreateChannel();
                    }
                }
            }
        }

        public void Connect<T>() where T: ITcpSyncChannel, new()
        {
            this._field_d = typeof(T);
            this.AsynCreateChannel();
        }

        public bool Detect()
        {
            lock (this)
            {
                if (this._field_c.Count != 0)
                {
                    if (this._field_c.Peek().a().Socket.Connected)
                    {
                        return true;
                    }
                    this._field_c.Dequeue();
                }
                return false;
            }
        }

        public void Dispose()
        {
            lock (this)
            {
                if (!this._field_e)
                {
                    this._field_e = true;
                    while (this._field_c.Count > 0)
                    {
                        this._field_c.Dequeue().a().Dispose();
                    }
                }
            }
        }

        public object Send(object data)
        {
            TcpSyncNode_a _a = this.c();
            if (_a == null)
            {
                throw NetTcpException.ConnectionIsNotAvailable();
            }
            using (_a)
            {
                return _a.a(data);
            }
        }

        public T Send<T>(object data)
        {
            using (TcpSyncNode_a _a = this.c())
            {
                return _a.Send<T>(data);
            }
        }

        public int Connections
        {
            get
            {
                return this._field_c.Count;
            }
        }

        public int DetectTime
        {
            [CompilerGenerated]
            get
            {
                return this._field_h;
            }
            [CompilerGenerated]
            set
            {
                this._field_h = value;
            }
        }

        public string Host
        {
            [CompilerGenerated]
            get
            {
                return this._field_f;
            }
            [CompilerGenerated]
            set
            {
                this._field_f = value;
            }
        }

        public bool IsDisposed
        {
            get
            {
                return this._field_e;
            }
        }

        public Exception LastError
        {
            get
            {
                return this._field_b;
            }
        }

        public int MaxConnections
        {
            [CompilerGenerated]
            get
            {
                return this._field_j;
            }
            [CompilerGenerated]
            set
            {
                this._field_j = value;
            }
        }

        public string Name
        {
            [CompilerGenerated]
            get
            {
                return this._field_i;
            }
            [CompilerGenerated]
            set
            {
                this._field_i = value;
            }
        }

        public int Port
        {
            [CompilerGenerated]
            get
            {
                return this._field_g;
            }
            [CompilerGenerated]
            set
            {
                this._field_g = value;
            }
        }

        public NodeStatus Status
        {
            [CompilerGenerated]
            get
            {
                return this._field_k;
            }
            [CompilerGenerated]
            set
            {
                this._field_k = value;
            }
        }

        internal class TcpSyncNode_a : IDisposable
        {
            private Exception _field_a;
            [CompilerGenerated]
            private TcpSyncNode _field_b;
            [CompilerGenerated]
            private ITcpSyncChannel _field_c;

            [CompilerGenerated]
            public ITcpSyncChannel a()
            {
                return this._field_c;
            }

            [CompilerGenerated]
            internal void a(ITcpSyncChannel A_0)
            {
                this._field_c = A_0;
            }

            [CompilerGenerated]
            internal void a(TcpSyncNode A_0)
            {
                this._field_b = A_0;
            }

            public object a(object A_0)
            {
                object obj2;
                try
                {
                    obj2 = this.a().Send(A_0);
                }
                catch (Exception exception)
                {
                    this._field_a = exception;
                    throw exception;
                }
                return obj2;
            }

            [CompilerGenerated]
            internal TcpSyncNode b()
            {
                return this._field_b;
            }

            public void Dispose()
            {
                lock (this)
                {
                    if (this.b() != null)
                    {
                        if (!this.a().IsDisplsed && this.a().Connected)
                        {
                            this.b().a(this);
                            if (this.b().Status == NodeStatus.Error)
                            {
                                this.b().Status = NodeStatus.None;
                                this.b().AsynCreateChannel();
                            }
                        }
                        else
                        {
                            if (this.b().Connections == 0)
                            {
                                this.b().a(this._field_a);
                            }
                            this.a((TcpSyncNode) null);
                        }
                    }
                }
            }

            public T Send<T>(object data)
            {
                T local;
                try
                {
                    local = (T) this.a().Send(data);
                }
                catch (Exception exception)
                {
                    this._field_a = exception;
                    throw exception;
                }
                return local;
            }
        }
    }
}

